<template>
  <el-switch v-model="subtitlesSwitch" @change="subtitlesChange" />
  <button @click="handleClickAllInfo">获取舞台所有元素信息</button>
  <div id="imageContainer"></div>
  <button @click="GenerateImage">Generate Image</button>
  <div id="container"></div>
  <teleport to='body'>
    <ActionBox ref="ActionBoxRef" />
  </teleport>
</template>
<script lang="tsx" setup>
import { onMounted, ref, nextTick, defineExpose } from 'vue'
import { handleClickUp, handleClickDown, handleClickTop, handleClickBottom, handleClickDeleteShape } from './components/actionBox.tsx'
import Konva from 'konva'
import ActionBox from './components/actionBox.vue'
import demo from '@/assets/images/production/demo.png'
import demo1 from '@/assets/images/production/idcard1.jpg'
import demo2 from '@/assets/images/production/word.png'

// 提示框盒子实例
const ActionBoxRef = ref()
// 舞台
let stage:Konva.Stage
// 图层
let layer:Konva.Layer
// 背景图图层
let backgroundLayer:Konva.Layer
// 控制器
let transformer:Konva.Transformer
// 字幕对象
let subtitles:Konva.Text
// 字母对象开关
let subtitlesSwitch = ref(false)
// 缩放比例
const scale = ref(1)
// 舞台位移的尺寸(X)
const translateX = ref('0px')
// 舞台位移的尺寸(Y)
const translateY = ref('0px')
// 初始化创建舞台
function initStage() {
  // 创建舞台
  // 默认创建的画布是 1920 * 1080
  stage = new Konva.Stage({
    container: 'container',
    width: 1920,
    height: 1080
  })
  // 创建背景图图层
  backgroundLayer = new Konva.Layer();
  stage.add(backgroundLayer);
  // 创建图层
  layer = new Konva.Layer()
  stage.add(layer)
  transformer = new Konva.Transformer({
    borderStroke: '#17B3A3', // 边框颜色
    borderStrokeWidth: 5, // 边框宽度
    anchorStroke: '#17B3A3', // 控制点边框颜色
    anchorFill: '#17B3A3',   // 控制点填充颜色
    anchorSize: 40,       // 控制点大小
    anchorCornerRadius: 20, // 控制点圆角半径
    rotateEnabled: false  // 禁用旋转
  });
  layer.add(transformer);

  // 处理图形点击事件
  stage.on('click', (e) => {
    ActionBoxRef.value.setActionBoxHidden()
    // 如果点击的是舞台背景，则清除选中状态
    
    // 如果图形的背景图，则不需要添加变压器
    const clickedShape = e.target;
    
    if (clickedShape === stage || clickedShape.attrs.name === 'background') {
      transformer.nodes([]);
      layer.draw();
      return;
    }
    
    transformer.nodes([clickedShape]);
    if(clickedShape.attrs.name && clickedShape.attrs.name === 'mote'){
      transformer.rotateEnabled(false)
    }else{
      transformer.rotateEnabled(true)
    }
    // 确保变压器在最顶层
    transformer.moveToTop();
    layer.draw();
  });
  stage.on('contextmenu', (e) => {
    // 禁止默认的右键菜单
    e.evt.preventDefault()
    // 获取鼠标右键点击时在页面中的坐标
    const pageX = e.evt.pageX;
    const pageY = e.evt.pageY;
    // 事件对象
    const clickedShape = e.target;
    // 如果点击的不是图形，或者点击的是背景图
    if (clickedShape === stage || clickedShape.attrs.name === 'background') {
      ActionBoxRef.value.setActionBoxHidden()
      transformer.nodes([]);
      layer.draw();
      return;
    }

    // 如果点击的是图形，则选中该图形
    transformer.nodes([clickedShape]);
    // 确保变压器在最顶层
    transformer.moveToTop();
    layer.draw();
    ActionBoxRef.value.setActionBoxShow(pageY, pageX)
    // 上移一层
    handleClickUp.value = () => {
      clickedShape.moveUp()
      layer.draw();
      ActionBoxRef.value.setActionBoxHidden()
    }
    // 下移一层
    handleClickDown.value = () => {
      clickedShape.moveDown()
      layer.draw();
      ActionBoxRef.value.setActionBoxHidden()
    }
    // 置顶
    handleClickTop.value = () => {
      clickedShape.moveToTop()
      layer.draw();
      ActionBoxRef.value.setActionBoxHidden()
    }
    // 置底
    handleClickBottom.value = () => {
      clickedShape.moveToBottom()
      layer.draw();
      ActionBoxRef.value.setActionBoxHidden()
    }
    // 删除图形
    handleClickDeleteShape.value = () => {
      clickedShape.remove()
      transformer.nodes([]);
      layer.draw();
      ActionBoxRef.value.setActionBoxHidden()
    }
  })
}
// 缩放舞台的方法-横屏(16:9)
function cross(){
  stage.width(1920);
  stage.height(1080);
  stage.batchDraw();
  nextTick(() => {
    const container = document.querySelector('#container') as HTMLDivElement;
    const containerWidth = container.offsetWidth;
    const containerHeight = container.offsetHeight;
    // 计算缩放比例
    const scaleX = containerWidth / 1920;
    const scaleY = containerHeight / 1080;
    scale.value = Math.min(scaleX, scaleY);
  }).then(() =>{
    translateStage()
  })
}
// 缩放舞台画布的方法-竖屏(9: 16)
function vertical(){
  stage.width(1080);
  stage.height(1920);
  stage.batchDraw();
  nextTick(() => {
    const container = document.querySelector('#container') as HTMLDivElement;
    const containerWidth = container.offsetWidth;
    const containerHeight = container.offsetHeight;
    // 计算缩放比例
    const scaleX = containerWidth / 1080;
    const scaleY = containerHeight / 1920;
    scale.value = Math.min(scaleX, scaleY);
  }).then(() =>{
    translateStage()
  })
}
// 对舞台位移的方法
function translateStage(){
  const stageSizeObject = getScaledElementSize('.konvajs-content')
  if(!stageSizeObject){
    return
  }
  // 舞台缩放后的实际尺寸
  const {width: stageWidth, height: stageHeight} = stageSizeObject
  // 舞台容器的实际尺寸
  const container = document.querySelector('#container') as HTMLDivElement;
  const containerWidth = container.offsetWidth;
  const containerHeight = container.offsetHeight;
  // 计算出舞台位移的尺寸
  translateX.value = (containerWidth - stageWidth) / 2 + 'px'
  translateY.value = (containerHeight - stageHeight) / 2 + 'px'
}
onMounted(() => {
  initStage()
  vertical()
  stageAddMoteImage(demo)
  stageAddOtherImage(demo2)
  // stageAddVideo('https://www.w3schools.com/html/mov_bbb.mp4')
  stageAddBackground()
})

// 往画布添加模特图片
function stageAddMoteImage(url: string){
  let imageObj = new Image();
  imageObj.src = url;
  imageObj.onload = function() {
    // 计算图片的宽高比例
    const imgRatio = imageObj.width / imageObj.height;
    const stageHeight = stage.height();

    // 计算适应舞台高度后的宽度
    const imgHeight = stageHeight;
    const imgWidth = imgHeight * imgRatio;

    // 计算图片居中位置
    const x = (stage.width() - imgWidth) / 2;
    const y = 0; // 高度适应舞台高度，y坐标为0

    const konvaImage = new Konva.Image({
      name: 'mote',
      x: x,
      y: y,
      image: imageObj,
      width: imgWidth,
      height: imgHeight,
      draggable: true
    });

    layer.add(konvaImage);
    layer.draw();
  };
}
// 往画布添加其他素材图片
function stageAddOtherImage(url: string){
  let imageObj = new Image();
  imageObj.src = url;
  imageObj.onload = function() {
    const imgWidth = imageObj.width;
    const imgHeight = imageObj.height;
    const stageWidth = stage.width();
    const stageHeight = stage.height();

    let newWidth, newHeight, x, y;

    // 第一种情况：图片宽度或高度大于舞台时，按比例缩放
    if (imgWidth > stageWidth || imgHeight > stageHeight) {
      const widthRatio = stageWidth / imgWidth;
      const heightRatio = stageHeight / imgHeight;
      const scale = Math.min(widthRatio, heightRatio);

      newWidth = imgWidth * scale;
      newHeight = imgHeight * scale;
    } else {
      // 第二种情况：图片宽高小于舞台时，按照图片尺寸渲染
      newWidth = imgWidth;
      newHeight = imgHeight;
    }

    // 计算图片居中位置
    x = (stageWidth - newWidth) / 2;
    y = (stageHeight - newHeight) / 2;

    const konvaImage = new Konva.Image({
      x: x,
      y: y,
      image: imageObj,
      width: newWidth,
      height: newHeight,
      draggable: true
    });
    layer.add(konvaImage);
    layer.draw();
  }
}
// 往画布中添加视频
function stageAddVideo(url: string){
  let videoElement = document.createElement('video');
  videoElement.src = url;
  videoElement.autoplay = true;
  videoElement.loop = true;
  videoElement.muted = true;

  videoElement.onloadedmetadata = function() {
    const videoWidth = videoElement.videoWidth;
    const videoHeight = videoElement.videoHeight;
    const stageWidth = stage.width();
    const stageHeight = stage.height();

    let newWidth, newHeight, x, y;

    // 第一种情况：视频宽度或高度大于舞台时，按比例缩放
    if (videoWidth > stageWidth || videoHeight > stageHeight) {
      const widthRatio = stageWidth / videoWidth;
      const heightRatio = stageHeight / videoHeight;
      const scale = Math.min(widthRatio, heightRatio);

      newWidth = videoWidth * scale;
      newHeight = videoHeight * scale;
    } else {
      // 第二种情况：视频宽高小于舞台时，按照视频原始尺寸渲染
      newWidth = videoWidth;
      newHeight = videoHeight;
    }

    // 计算视频居中位置
    x = (stageWidth - newWidth) / 2;
    y = (stageHeight - newHeight) / 2;

    const konvaVideo = new Konva.Image({
      x: x,
      y: y,
      image: videoElement,
      width: newWidth,
      height: newHeight,
      draggable: true
    });

    layer.add(konvaVideo);
    layer.draw();

    // 更新视频帧
    function updateFrame() {
      konvaVideo.cache();
      const currentLayer = konvaVideo.getLayer();
      if (currentLayer) {
          currentLayer.batchDraw();
      }
      requestAnimationFrame(updateFrame);
    }
    videoElement.play().catch(error => {
      console.error('视频播放失败:', error);
    });
    updateFrame();
  };
}
// 字幕开关事件
const subtitlesChange = (value:boolean):void => {
  if(value){
    stageAddSubtitle()
  }else{
    stageRemoveSubtitle()
  }
}

// 往画布中添加字幕
function stageAddSubtitle(){
  subtitles = new Konva.Text({
    text: '字幕展示',
    fontSize: 50,
    fontFamily: 'Arial',
    fill: 'black',
    draggable: true
  });

  // 设置文本对象的位置，靠舞台底部并水平居中
  subtitles.x((stage.width() - subtitles.width()) / 2);
  subtitles.y(stage.height() * 0.9); // 距离底部10像素

  // 添加文本对象到图层
  layer.add(subtitles);

  // 更新图层
  layer.draw();
}
// 移除画布中的字幕
function stageRemoveSubtitle(){
  subtitles.remove();
  layer.draw(); 
}
// 设置图层背景图
function stageAddBackground(){
  // 加载背景图片
  const imageObj = new Image();
  imageObj.onload = function() {
    var bgImage = new Konva.Image({
      name: 'background',
      x: 0,
      y: 0,
      image: imageObj,
      width: stage.width(),
      height: stage.height()
    });

    backgroundLayer.add(bgImage);
    backgroundLayer.draw();
  };
  imageObj.src = demo1
}

// 获取缩放后元素的实际大小
function getScaledElementSize(selector: string) {
  var element = document.querySelector(selector);
  if (!element) {
      console.error("元素未找到: " + selector);
      return null;
  }

  var computedStyle = window.getComputedStyle(element);
  var width = parseFloat(computedStyle.getPropertyValue('width'));
  var height = parseFloat(computedStyle.getPropertyValue('height'));

  // 获取缩放比例
  var transform = computedStyle.getPropertyValue('transform');
  if (transform === 'none') {
      return { width: width, height: height };
  }

  var matrix = transform.match(/^matrix\((.+)\)$/);
  if (!matrix) {
      console.error("无法解析transform属性: " + transform);
      return null;
  }

  var values = matrix[1].split(', ');
  var scaleX = parseFloat(values[0]);
  var scaleY = parseFloat(values[3]);

  // 计算实际大小
  var actualWidth = width * scaleX;
  var actualHeight = height * scaleY;

  return { width: actualWidth, height: actualHeight };
}

const handleClickAllInfo = () => {
  console.log(stage.getChildren());
}
const GenerateImage = () => {
  var dataURL = stage.toDataURL();
    var img = new Image();
    img.src = dataURL;

    // 清空之前的图像（如果有）
    var imageContainer = document.getElementById('imageContainer');
    imageContainer.innerHTML = '';
    imageContainer.appendChild(img);
}

defineExpose({
  cross,
  vertical,
  stageAddMoteImage,
  stageAddOtherImage,
  stageAddVideo,
  stageAddSubtitle,
  stageRemoveSubtitle,
  stageAddBackground
});
</script>
<style lang="less" scoped>
#container{
  width: 1000px;
  height: 800px;
  overflow: hidden;
  margin: 0 10px 10px; 
  background-color: #aaa;
}
:deep(.konvajs-content){
  background-color: #fff;
  transform-origin: top left;
  transform: translate(v-bind(translateX),v-bind(translateY)) scale(v-bind(scale));
}
</style>